let $cont = $(".webgl-content")
let contW = $cont.width()
let contH = $cont.height()
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')

let radius = 160
let showingDetail = false
let grabbedEarth = false
let grabbedTimeline = false

let renderer
let scene
let camera

let objects = [] //存储可以交互的对象
let Loader = new THREE.TextureLoader
let raycaster = new THREE.Raycaster
let mouse = new THREE.Vector2
let mouseOnMouseDown = new THREE.Vector2
let targetSceneRotation = new THREE.Euler
let targetEarthRotation = new THREE.Euler
let targetEarthRotationOnMouseDown = new THREE.Euler
let targetRotation = new THREE.Euler(-Math.PI / 180 * 91, 0, 0)
let targetRotationOnMouseDown = new THREE.Euler
let earth
let earthCta
let timeline
let skybox
let earthOrgRot = new THREE.Euler
let earthCtaOrgRot = new THREE.Euler
let closeBtn
let detailViewScreen
let detailViewScreenOrgRot = new THREE.Euler

init()

async function init(){
  [
    ['Borda', 'url(font/Borda.otf)'],
    ['Borda-Bold', 'url(font/Borda-Bold.woff)'],
  ].forEach(el => {
    let font = new FontFace(...el)
    font.load()
    document.fonts.add(font)
  })
  await document.fonts.ready

  renderer = new THREE.WebGLRenderer({antialias: true})
  renderer.setClearColor(0x000000)
  renderer.setSize(contW, contH)
  let webgl = renderer.domElement
  $cont.append(webgl)

  scene = new THREE.Scene
  camera = new THREE.PerspectiveCamera(45, contW / contH, 1, 100000)
  camera.position.z = 550

  addLights()
  addSkybox()
  addEarth()
  addOuterRing()
  addCityLines()
  createHotSpot()
  addTimeline()
  addCloseBtn()
  addDetailViewScreen()

  render()
  onWindowResize()
  window.addEventListener('resize', onWindowResize)
  document.addEventListener('mousedown', onDocumentMouseDown)
  document.addEventListener('mousemove', onDocumentMouseMove)
  document.addEventListener('mouseup', onDocumentMouseUp)
  document.addEventListener('mouseout', onDocumentMouseUp)
}

// 根据物体的经纬度和高度计算其在右手笛卡尔坐标系中的坐标
// 这个计算方法是根据地图的形式来的，比如说太平洋在中间还是大西洋在中间
function latLngToVector3(lat, lon, radius) {
  var phi = lat * Math.PI / 180
  var theta = (lon - 180) * Math.PI / 180
  var x = - radius * Math.cos(phi) * Math.cos(theta)
  var y = radius * Math.sin(phi)
  var z = radius * Math.cos(phi) * Math.sin(theta)
  return new THREE.Vector3(x, y, z)
}

function addObjectAtLatLng(obj, lat, lng, height = 0) {
  var pos = latLngToVector3(lat, lng, radius + height)
  obj.position.copy(pos)
  // 由于默认的up是(0,1,0), 直接指向地球(0,0,0)会导致倒置
  // 所以指向同一直线上的反方向。当然直接multiply只在地球(0,0,0)时有效
  obj.lookAt(pos.clone().multiplyScalar(1.1))
  earth.add(obj)
}

function getYearPng(year){
  canvas.width = 128
  canvas.height = 64
  ctx.font = '66px Borda-Bold'
  ctx.fillStyle = '#81ffff'
  ctx.fillText(year.toString(), 0, 56)
  return canvas.toDataURL("image/png")
}

function getCityPng(text){
  canvas.width = 256
  canvas.height = 64
  let [city, country] = text.split(',').map(r=>r.trim())
  ctx.fillStyle = '#81ffff'
  ctx.font = '36px Borda-Bold'
  ctx.fillText(city, 3, 34)
  ctx.font = '20px Borda-Bold'
  ctx.fillText(country, 3, 56)
  return canvas.toDataURL("image/png")
}

function getHotspotPng(time, name){
  canvas.width = 1024
  canvas.height = 256
  ctx.fillStyle = 'rgba(255,160,67,1)'
  ctx.font = '40px Borda-Bold'
  ctx.fillText(time, 10, 100)
  ctx.font = '76px Borda-Bold'
  ctx.fillText(name, 0, 200)
  return canvas.toDataURL("image/png")
}

function getDatePng(date){
  canvas.width = 256
  canvas.height = 64
  ctx.font = '66px Borda-Bold'
  ctx.fillStyle = '#81ffff'
  ctx.fillText(date, 0, 56)
  return canvas.toDataURL("image/png")
}

function addLights(){
  let dirLight1 = new THREE.PointLight(0xD0FDFF, 1.1, 0)
  dirLight1.position.set(0, 0, 600)
  dirLight1.lookAt(new THREE.Vector3)
  scene.add(dirLight1)

  let dirLight2 = new THREE.DirectionalLight(0x7efaff, 1)
  dirLight2.position.set(400, 400, 100)
  scene.add(dirLight2)
}

function addSkybox(){
  let geo = new THREE.SphereGeometry(1500, 40, 40)
  let mat = new THREE.MeshBasicMaterial({
    color: 0x7efaff,
    map: Loader.load("img/stars.jpg"),
    side: THREE.BackSide,
    opacity: .2,
    transparent: true,
    blending: THREE.AdditiveBlending,
  })
  skybox = new THREE.Mesh(geo, mat)
  skybox.name = 'skybox'
  scene.add(skybox)
}

function addEarth(){
  //地球本体，包含了一系列相关图层
  let geo = new THREE.SphereGeometry(radius, 50, 50)
  let mat = new THREE.MeshLambertMaterial({
    map: Loader.load('img/earth.jpg')
  })
  earth = new THREE.Mesh(geo, mat)
  earth.name = 'earth'
  //添加地图热点层
  for(let i of Array(4).keys()){
    let geo = new THREE.SphereGeometry(radius + 1, 50, 50)
    let mat = new THREE.MeshLambertMaterial({
      transparent: true,
      color: 0xff8340,
      blending: THREE.AdditiveBlending,
      opacity: .4,
      map: Loader.load(`img/fire${i + 1}.png`), 
    })
    let fire = new THREE.Mesh(geo, mat)
    fire.name = 'fire' + i
    earth.add(fire)
  }
  //添加地球包络
  for(let i of Array(2).keys()){
    let geo = new THREE.SphereGeometry(radius + 15, i ? 20 : 40, 30)
    let egh = new THREE.LineSegments(
      new THREE.EdgesGeometry(geo),
      new THREE.LineBasicMaterial({
        color: 0x2AC7CC,
        transparent: true,
        opacity: .08 * (i + 1),
      })
    )
    egh.name = 'earth-wrapper'
    earth.add(egh)
  }
  {//添加国家边界浮层
    let geo = new THREE.SphereGeometry(radius + 15, 50, 50);
    let mat = new THREE.MeshLambertMaterial({
      blending: THREE.AdditiveBlending,
      transparent: true,
      color: 0x2AC7CC,
      opacity: .9,
      map: Loader.load("img/earth_political_alpha.png")
    })
    let earthPol = new THREE.Mesh(geo, mat)
    earthPol.name = 'earth-map-border'
    objects.push(earthPol)
    earth.add(earthPol)
  }
  {//添加地球赤道环绕的一圈时间刻度
    let ring = new THREE.Object3D
    ring.name = 'earth-ring'
    let r = radius + 60
    let t = Math.PI / 180 * 2
    let yr = 1996
    let mat = new THREE.LineBasicMaterial({
      color: 0x6FD5F0,
      transparent: true,
      opacity: .4,
    })
    let lineGeo = new THREE.Geometry
    for(let i of Array(180).keys()){
      let x = r * Math.cos(t * i)
      let z = r * Math.sin(t * i)
      //小刻度
      lineGeo.vertices.push(new THREE.Vector3(x * .985, 0, z * .985))
      lineGeo.vertices.push(new THREE.Vector3(x, 0, z))
      //大刻度
      if (i % 5 == 0) {
        lineGeo.vertices.push(new THREE.Vector3(x * .965, 0, z * .965))
        lineGeo.vertices.push(new THREE.Vector3(x, 0, z))
        lineGeo.vertices.push(new THREE.Vector3(x * .965, 0, z * .965))
        lineGeo.vertices.push(new THREE.Vector3(x, 0, z))
      }
      //添加随机的竖条修饰
      if (Math.random() < 0.1) {
        lineGeo.vertices.push(new THREE.Vector3(x, 0, z))
        lineGeo.vertices.push(new THREE.Vector3(x, 5, z))
      }
      //添加时间标签
      if (i % 10 == 0) {
        let pgeo = new THREE.PlaneGeometry(6, 3)
        let pmat = new THREE.MeshPhongMaterial({
          map: Loader.load(getYearPng(yr++)),
          transparent: true,
          side: THREE.DoubleSide
        })
        let p = new THREE.Mesh(pgeo, pmat)
        p.position.set(x * 1.02, -1, z * 1.02)
        p.lookAt(p.position.clone().multiplyScalar(1.1))
        ring.add(p)
      }
    }
    let line = new THREE.LineSegments(lineGeo, mat)
    ring.add(line)
    earth.add(ring)
  }
  //包含了地球的一个层，用来限制地轴旋转
  earthCta = new THREE.Object3D
  earthCta.rotation.x = (Math.PI / 180) * 10
  earthCta.rotation.z = (Math.PI / 180) * -20
  earthCta.rotation.y = (Math.PI / 180) * -20
  earthCta.add(earth)
  scene.add(earthCta)
}

function addOuterRing(){
  let geo = new THREE.PlaneGeometry(480, 480, 1, 1);
  let mat = new THREE.MeshBasicMaterial({
    map: Loader.load("img/radial_layers_medium.jpg"),
    transparent: true,
    opacity: .4,
    blending: THREE.AdditiveBlending
  })
  let outerRing = new THREE.Mesh(geo, mat)
  outerRing.position.z = 320
  outerRing.name = 'outer-ring'
  scene.add(outerRing)
}

function addCityLines(){
  let lineMatOrange = new THREE.MeshBasicMaterial({
    color: 0xff8340,
    transparent: true,
    opacity: 0.3,
    blending: THREE.AdditiveBlending,
  })
  let hexMat = new THREE.MeshBasicMaterial({
    color: 0xff8340,
    transparent: true,
    opacity: 0.5,
  })
  for(let j of Array(4).keys()){
    for(let i of Array(36).keys()){
      let line = new THREE.Object3D()
      line.city = IDR.cities[`phase${j+1}`][i]

      let hexGeo = new THREE.CircleGeometry(2, 6, 5)
      hexGeo.vertices.shift()
      line.hex = new THREE.LineLoop(hexGeo, hexMat)
      line.hex.z = 40
      line.add(line.hex)

      let h = Math.random() * 80 + 50
      let geo = new THREE.Geometry()
      geo.vertices.push(new THREE.Vector3(0, 0, 0))
      geo.vertices.push(new THREE.Vector3(0, 0, h))
      line.lineBlue = new THREE.LineSegments(geo, lineMatOrange)
      line.add(line.lineBlue)

      let labelGeo = new THREE.PlaneGeometry(32, 8)
      let labelMat = new THREE.MeshBasicMaterial({
        side: THREE.DoubleSide,
        blending: THREE.AdditiveBlending,
        map: Loader.load(getCityPng(line.city.name)),
        transparent: true,
        opacity: 1,
        depthWrite: false,
      })
      line.label = new THREE.Mesh(labelGeo, labelMat)
      line.label.position.set(16, 0, h)
      line.add(line.label)

      addObjectAtLatLng(line, line.city.lat, line.city.lng, 17)
    }
  }
}

function getSixGeometry(name){
  let	hotspot = new THREE.Object3D
  {//前两层六边形
    let s = new THREE.Shape
    s.moveTo(0, 10)
    ;[
      [9,5],[9,-5],[0,-10],[0,-6],[5,-3],[5,3],[0,6]
    ].forEach(e => s.lineTo(...e))
    let geo = new THREE.ShapeGeometry(s)
    let mat = new THREE.MeshBasicMaterial({
      blending: THREE.AdditiveBlending,
      color: 0xff8340,
      transparent: true,
      opacity: .6,
    })
    let hexSeg1 = new THREE.Mesh(geo, mat)
    let hexSeg2 = new THREE.Mesh(geo, mat)
    hexSeg1.rotation.z = (Math.PI / 180) * -60
    hexSeg2.rotation.z = (Math.PI / 180) * 120
    hexSeg2.position.z = 3
    hotspot.add(hexSeg1)
    hotspot.add(hexSeg2)
  }
  {//第三层六边形
    let s = new THREE.Shape
    s.moveTo(0, 10)
    ;[
      [9,5],[9,-5],[0,-10],[-9,-5],[-9,5],[0,10]
    ].forEach(e => s.lineTo(...e))
    let geo = new THREE.ShapeGeometry(s)
    let mat = new THREE.LineBasicMaterial({
      blending: THREE.AdditiveBlending,
      color: 0xff8340,
      transparent: true,
      opacity: .8,
    })
    let hexSeg3 = new THREE.Line(geo, mat)
    hexSeg3.position.set(.25, 0, 6)
    hexSeg3.scale.set(1.2, 1.2, 1.2)
    hotspot.add(hexSeg3)
  }
  {//第四层六边形
    let s = new THREE.Shape
    s.moveTo(0, 10)
    ;[
      [9,5],[9,-5],[0,-10],[-9,-5],[-8,-4.5],[0,-9],[8,-4.5],[8,4.5],[0,9]
    ].forEach(e => s.lineTo(...e))
    let geo = new THREE.ShapeGeometry(s)
    let mat = new THREE.MeshBasicMaterial({
      blending: THREE.AdditiveBlending,
      color: 0xff8340,
      transparent: true,
      opacity: .8,
      side: THREE.DoubleSide
    })
    let hexSeg4 = new THREE.Mesh(geo, mat)
    hexSeg4.scale.set(1.5, 1.5, 1.5)
    hexSeg4.position.set(.4, 0, 9)
    hotspot.add(hexSeg4)
  }
  {//中心加号准星
    let geo = new THREE.Geometry
    geo.vertices = [
      [-3,0,0],[3,0,0],[0,3,0],[0,-3,0]
    ].map(e => new THREE.Vector3(...e))
    let mat = new THREE.LineBasicMaterial({
      blending: THREE.AdditiveBlending,
      color: 0xff8340,
      transparent: true,
      opacity: .9,
    })
    let plus = new THREE.LineSegments(geo, mat)
    plus.position.z = 12
    hotspot.add(plus)
  }
  {//周围的装饰线,四根
    let mat = new THREE.LineBasicMaterial({
      blending: THREE.AdditiveBlending,
      color: 0xff8340,
      transparent: true,
      opacity: .5,
    })
    let geo = new THREE.Geometry
    geo.vertices = [
      [15,0,0],[20,0,0],[-15,0,0],[-20,0,0],
      [-10,-15,0],[-12.5,-19.3,0],[-7.5,10.7,0],[-10,15,0]
    ].map(e => new THREE.Vector3(...e))
    let line = new THREE.LineSegments(geo, mat)
    line.position.z = 9
    hotspot.add(line)
  }
  {//用于处理事件点击的隐藏图形
    let geo = new THREE.CircleGeometry(15, 6, .5)
    let mat = new THREE.MeshBasicMaterial({
      visible: false,
    })
    let hidden = new THREE.Mesh(geo, mat)
    hidden.position.z = 9
    hidden.name = name
    hotspot.add(hidden)
    objects.push(hidden)
  }
  return hotspot
}

function createHotSpot() {
  let	hotspot = getSixGeometry('hotspot-h')
  {//高耸的线
    let geo = new THREE.Geometry()
    geo.vertices.push(new THREE.Vector3(0, 0, 0))
    geo.vertices.push(new THREE.Vector3(0, 0, 250))
    let mat = new THREE.LineBasicMaterial({
      blending: THREE.AdditiveBlending,
      color: 0xff8340,
      transparent: true,
      opacity: .5,
    })
    let line = new THREE.Line(geo, mat)
    hotspot.add(line)
  }
  {//上面的文字
    let geo = new THREE.PlaneGeometry(80, 20)
    let mat = new THREE.MeshBasicMaterial({
      side: THREE.DoubleSide,
      blending: THREE.AdditiveBlending,
      map: Loader.load(getHotspotPng('2005-01-20', 'MOON BASE OPERATIONAL')),
      transparent: true,
    })
    let title = new THREE.Mesh(geo, mat)
    title.position.set(56, 10, 0)
    hotspot.add(title)
  }
  hotspot.scale.set(1.7,1.7,1.7)
  addObjectAtLatLng(hotspot, 19.4333, -99.1333, 18)
}

function addCloseBtn(){
  closeBtn = getSixGeometry('closebtn')
  scene.add(closeBtn)
  closeBtn.show = function(){
    closeBtn.lookAt(camera.position)
    closeBtn.rotation.x = (Math.PI / 180) * - 135
    closeBtn.position.z = 270
    closeBtn.position.y = -300
    new TWEEN.Tween(closeBtn.position)
      .to({y: -305}, 1000)
      .delay(1500)
      .start()
    new TWEEN.Tween(closeBtn.rotation)
      .to({x: (Math.PI / 180) * -45}, 1000)
      .delay(2000)
      .easing(TWEEN.Easing.Quadratic.InOut)
      .start()
  }
  closeBtn.hide = function(){
    new TWEEN.Tween(closeBtn.position)
      .to({y: -305 - 300}, 3000)
      .easing(TWEEN.Easing.Quadratic.InOut)
      .start()
    new TWEEN.Tween(closeBtn.rotation)
      .to({x: (Math.PI / 180) * -135}, 1000)
      .easing(TWEEN.Easing.Quadratic.Out)
      .start()
  }
}

function addTimeline(){
  let r = 120
  let t = 2 * Math.PI / 360
  timeline = new THREE.Object3D
  timeline.name = 'timeline'
  {//圆盘骨架和外层刻度
    let outerDial = new THREE.Object3D
    {//内层表盘圆弧
      let geo = new THREE.RingGeometry(r + 9, r + 17, 200, 1)
      geo.rotateX(Math.PI / 2)
      let mat = new THREE.MeshBasicMaterial({
        transparent: true,
        opacity: .1,
        color: 0x6FD5F0,
        side: THREE.DoubleSide,
      })
      let circle = new THREE.Mesh(geo, mat)
      outerDial.add(circle)
    }
    {//外层表盘圆弧
      let geo = new THREE.RingGeometry(r + 17, r + 19, 200, 1)
      geo.rotateX(Math.PI / 2)
      let mat = new THREE.MeshBasicMaterial({
        transparent: true,
        opacity: .2,
        color: 0x6FD5F0,
        side: THREE.DoubleSide,
      })
      let circle = new THREE.Mesh(geo, mat)
      outerDial.add(circle)
    }
    {//看不见的用来处理拖动事件的圆弧
      let geo = new THREE.RingGeometry(r - 8, r + 19, 200, 1)
      geo.rotateX(Math.PI / 2)
      let mat = new THREE.MeshBasicMaterial({
        visible: false,
        side: THREE.BackSide,
      })
      let circle = new THREE.Mesh(geo, mat)
      circle.name = 'timeline-h'
      objects.push(circle)
      outerDial.add(circle)
    }

    let lineGeo = new THREE.Geometry
    let mat = new THREE.LineBasicMaterial({
      transparent: true,
      opacity: .4,
      color: 0x6FD5F0,
    })
    for(let i = 0; i < 360; i += 4){
      let x = (r + 12) * Math.cos(t * i)
      let z = (r + 12) * Math.sin(t * i)
      lineGeo.vertices.push(new THREE.Vector3(x * 1.07, 0, z * 1.07))
      lineGeo.vertices.push(new THREE.Vector3(x * 1.05, 0, z * 1.05))
    }
    let line = new THREE.LineSegments(lineGeo, mat)
    outerDial.add(line)
    outerDial.rotation.y = Math.PI / 180 * 80
    timeline.add(outerDial)
    timeline.outerDial = outerDial
  }
  {//刻度盘指示器
    let pointer = new THREE.Object3D
    {//外层圆圈
      let s = new THREE.Shape
      let offset = 6
      s.absarc(0, 0, r, Math.PI / 180 * (90 - offset), Math.PI / 180 * (90 + offset), true)
      s.lineTo((r - 10) * Math.cos(t * 90), (r - 10) * Math.sin(t * 90))
      s.lineTo(r * Math.cos(t * (90 - offset)), r * Math.sin(t * (90 - offset)))
      let geo = new THREE.ShapeGeometry(s)
      let mat = new THREE.LineBasicMaterial({
        transparent: true,
        opacity: .3,
        color: 0x6FD5F0,
      })
      let tp = new THREE.LineLoop(geo, mat)
      pointer.add(tp)
    }
    {//上下指针
      let s = new THREE.Shape
      s.moveTo(-.7, 0)
      s.lineTo(0, -1.8)
      s.lineTo(.7, 0)
      s.lineTo(-.7, 0)
      let geo = new THREE.ShapeGeometry(s)
      let mat = new THREE.MeshLambertMaterial({
        transparent: true,
        opacity: .6,
        color: 0x7efaff,
        side: THREE.DoubleSide,
      })
      let arrow0 = new THREE.Mesh(geo, mat)
      arrow0.position.y = 121
      arrow0.position.z -= .2
      let arrow1 = arrow0.clone()
      arrow1.rotation.z = Math.PI
      arrow1.position.z -= 4
      pointer.add(arrow0)
      pointer.add(arrow1)
    }
    {//下方双弧线
      let s = new THREE.Shape
      s.absarc(0, 0, r, Math.PI / 180 * 87, Math.PI / 180 * 75, true)
      s.lineTo(r * Math.cos(t * 75) - 2, r * Math.sin(t * 75) - 1)
      let geo = new THREE.ShapeGeometry(s)
      let mat = new THREE.LineBasicMaterial({
        transparent: true,
        opacity: .2,
        color: 0x7efaff,
      })
      let tp0 = new THREE.Line(geo, mat)
      tp0.position.z = -7
      let tp1 = tp0.clone()
      tp1.rotation.y = Math.PI
      pointer.add(tp0)
      pointer.add(tp1)
    }

    pointer.rotation.x = Math.PI / 180 * -90
    timeline.add(pointer)
  }
  {//盘上的刻度与字符，以及热点
    let dial = new THREE.Object3D
    let psize = 2.4
    let py = 1.7
    let yr = 1996
    let mat = new THREE.LineBasicMaterial({
      linewidth: 1,
      color: 0x6FD5F0,
      transparent: true,
      opacity: .7,
    })
    let lineGeo = new THREE.Geometry
    //刻度盘
    for(let i of Array(360).keys()){
      let x = r * Math.cos(t * i)
      let z = r * Math.sin(t * i)
      //普通小刻度
      lineGeo.vertices.push(...[
        [x * .985, 0, z * .985], [x, 0, z],
        [x * .96, 0, z * .96], [x * .965, 0, z * .965]
      ].map(e => new THREE.Vector3(...e)))
      //年份刻度
      if (i == 1 || ((i - 36) % 12 === 0 && i > 36 && i < 280)) {
        let p = new THREE.Mesh(
          new THREE.PlaneGeometry(psize * 2, psize),
          new THREE.MeshPhongMaterial({
            map: Loader.load(getYearPng(yr++)),
            transparent: true,
            opacity: 1,
          })
        )
        p.position.set(x, py, z)
        p.lookAt(new THREE.Vector3(0, 60, 0))
        dial.add(p)
        let geo = new THREE.Geometry
        geo.vertices.push(new THREE.Vector3(x * .96, 0, z * .96))
        geo.vertices.push(new THREE.Vector3(x * .99, 0, z * .99))
        let line = new THREE.Line(geo, mat)
        dial.add(line)
      }
      //几个日期刻度
      if ([7,19,31,43].includes(i)) {
        let d = ({
          7: '1996.07.02',
          19: '1996.07.03',
          31: '1996.07.04',
        })[i]
        if(i != 43){
          let p = new THREE.Mesh(
            new THREE.PlaneGeometry(psize * 4.1, psize * 1.1),
            new THREE.MeshPhongMaterial({
              map: Loader.load(getDatePng(d)),
              transparent: true,
            })
          )
          p.position.x = r * Math.cos(t * (i + psize + .6))
          p.position.y = py
          p.position.z = r * Math.sin(t * (i + psize + .6))
          p.lookAt(new THREE.Vector3(0, 60, 0))
          dial.add(p)
          // 添加有角度的斜杠号
          for (let j of Array(17).keys()) {
            let xh = (r - 3) * Math.cos(t * i + (.012 * j))
            let zh = (r - 3) * Math.sin(t * i + (.012 * j))
            let xh2 = (r - 5) * Math.cos(t * i + (.012 * j + .012))
            let zh2 = (r - 5) * Math.sin(t * i + (.012 * j + .012))
            lineGeo.vertices.push(new THREE.Vector3(xh, 0, zh))
            lineGeo.vertices.push(new THREE.Vector3(xh2, 0, zh2))
          }
        }
        lineGeo.vertices.push(new THREE.Vector3(x * .96, 0, z * .96))
        lineGeo.vertices.push(new THREE.Vector3(x * 1.05, 0, z * 1.05))
      }
    }
    let line = new THREE.LineSegments(lineGeo, mat)
    dial.add(line)
    //刻度盘上的热点
    for(let e of IDR.events){
      let pos
      if (e.year == 1996 && e.month < 7) {
        pos = e.month;
      } else if (e.year == 1996 && e.month == 7 && e.day < 5) {
        if (e.day == 2) { pos = 7; }
        if (e.day == 3) { pos = 19; }
        if (e.day == 4) { pos = 31; }
      } else {
        pos = Math.floor((e.year - 1997) * 12) + 47 + e.month + (e.day / 30);
      }
      let mat = new THREE.LineBasicMaterial({
        color: 0xFF9643,
        transparent: true,
        opacity: .6,
      })
      let geo = new THREE.CircleGeometry(1.2, 6)
      geo.vertices.shift()
      let hotspot = new THREE.LineLoop(geo, mat)
      hotspot.position.x = r * Math.cos(t * pos)
      hotspot.position.z = r * Math.sin(t * pos)
      hotspot.position.y = -1.5
      hotspot.lookAt(new THREE.Vector3)
      hotspot.rotation.z = Math.PI / 180 * 30
      dial.add(hotspot)
    }
    //添加日期的小热点
    for (let i of Array(4).keys()) {
      let mat = new THREE.LineBasicMaterial({
        color: 0xFF9643,
        transparent: true,
        opacity: .6,
      })
      let geo = new THREE.CircleGeometry(.6, 6)
      geo.vertices.shift()
      let hotspot = new THREE.LineLoop(geo, mat)
      let pos = [17,24,30,40][i]
      hotspot.position.x = r * Math.cos(t * pos)
      hotspot.position.z = r * Math.sin(t * pos)
      hotspot.position.y = -1.5
      hotspot.lookAt(new THREE.Vector3)
      hotspot.rotation.z = Math.PI / 180 * 30
      dial.add(hotspot)
    }
    dial.rotation.y = Math.PI / 180 * 91
    timeline.add(dial)
    timeline.dial = dial
  }
  timeline.rotation.x = Math.PI / 180 * 5
  timeline.position.z = 530 - contW * .01
  timeline.position.y = -55 - contW * .003
  scene.add(timeline)

  timeline.show = function(){
    new TWEEN.Tween(timeline.position)
      .to({y: -55 - contW * .003}, 3000)
			.easing(TWEEN.Easing.Quadratic.InOut)
      .start()
  }
  timeline.hide = function(){
		new TWEEN.Tween(timeline.position)
      .to({y: 40}, 4000)
			.easing(TWEEN.Easing.Quadratic.InOut)
      .start()
  }
}

function addDetailViewScreen() {
  detailViewScreen = new THREE.Object3D
  detailViewScreen.position.z = -30
  detailViewScreen.position.y = -225
  detailViewScreen.rotation.y = Math.PI / 180 * 180
  detailViewScreen.rotation.x = Math.PI / 180 * 30

  var geo = new THREE.SphereGeometry(radius * 2.5, 6, 3, 4.41, .6, 1.4, .3)
  var mat = new THREE.MeshLambertMaterial({
    opacity: .5,
    transparent: true,
    blending: THREE.AdditiveBlending,
    map: Loader.load('img/showscr.jpg')
  })

  let viewScreen = new THREE.Mesh(geo, mat)
  let egh = new THREE.LineSegments(
    new THREE.EdgesGeometry(geo), 
    new THREE.LineBasicMaterial({
      color: 0x7efaff,
      transparent: true,
      opacity: .2,
    })
  )
  egh.position.z = -1
  viewScreen.add(egh)
  detailViewScreen.add(viewScreen)
  scene.add(detailViewScreen)
}

function showDetailView(){
  earthOrgRot.copy(earth.rotation)
  earthCtaOrgRot.copy(earthCta.rotation)
  detailViewScreenOrgRot.copy(detailViewScreen.rotation)
  new TWEEN.Tween(earthCta.rotation)
    .to({ x: 0, y: 0, z: 0 }, 3000)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .start()
  new TWEEN.Tween(earth.rotation)
    .to({
      x: Math.PI / 4 - .15 * earthOrgRot.y,
      y: earthOrgRot.y
    }, 3000)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .onComplete(function () {
      targetEarthRotation.x = earth.rotation.y
      targetEarthRotation.y = earth.rotation.x
    })
    .start()
  new TWEEN.Tween(camera.rotation)
    .to({x: (Math.PI / 180) * -30}, 3000)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .start()
  new TWEEN.Tween(detailViewScreen.rotation)
    .to({x: (Math.PI / 180) * -15}, 3000)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .start()
  closeBtn.show()
  timeline.hide()
  showingDetail = true
}

function hideDetailView(){
  new TWEEN.Tween(earthCta.rotation)
    .to({
      x: earthCtaOrgRot.x,
      y: earthCtaOrgRot.y,
      z: earthCtaOrgRot.z
    }, 3000)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .start()
  new TWEEN.Tween(earth.rotation)
    .to({
      x: earthOrgRot.x,
      y: earthOrgRot.y,
      z: earthOrgRot.z,
    }, 3000)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .onComplete(function (){
      targetEarthRotation.x = earth.rotation.y
      targetEarthRotation.y = earth.rotation.x
    })
    .start()
  new TWEEN.Tween(camera.rotation)
    .to({ x: 0, y: 0 }, 3000)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .start()
  new TWEEN.Tween(detailViewScreen.rotation)
    .to({x: detailViewScreenOrgRot.x}, 4000)
    .start()
  closeBtn.hide()
  timeline.show()
  showingDetail = false
  targetSceneRotation.x = 0
  targetSceneRotation.y = 0
}

function onWindowResize(){
  contW = $cont.width()
  contH = $cont.height()
  renderer.setSize(contW, contH)
  camera.aspect = contW / contH
  camera.updateProjectionMatrix()
  if (contW < contH) {
    camera.position.z = 700
    timeline.position.z = 670 - contW * .01
    if (!showingDetail) {
      timeline.position.y = -60 - contW * .003
    }
  }else{
    camera.position.z = 550
    timeline.position.z = 530 - contW * .01
    if (!showingDetail) {
      timeline.position.y = -55 - contW * .003
    }
  }

}

function updateRaycaster(){
  let mouse = new THREE.Vector2
  mouse.x = (event.clientX / contW) * 2 - 1
  mouse.y = - (event.clientY / contH) * 2 + 1
  raycaster.setFromCamera(mouse, camera)
  let intersects = raycaster.intersectObjects(objects)
  if(intersects.length){
    return intersects[0].object
  }
  return {name: '', parent: {name: ''}, children: []}
}

function onDocumentMouseDown(event){
  mouseOnMouseDown.x = event.clientX
  mouseOnMouseDown.y = event.clientY
  grabbedEarth = false
  let obj = updateRaycaster()
  if(obj.name == 'earth-map-border'){
    targetEarthRotationOnMouseDown.copy(targetEarthRotation)
    grabbedEarth = true
  }else if(obj.name == 'timeline-h'){
    targetRotationOnMouseDown.x = targetRotation.x
    grabbedTimeline = true
  }else if(obj.name == 'hotspot-h'){
    showDetailView()
  }else if(obj.name == 'closebtn'){
    hideDetailView()
  }
}

function onDocumentMouseMove(event){
  mouse.x = event.clientX
  mouse.y = event.clientY
  if(grabbedTimeline){
    targetRotation.x = targetRotationOnMouseDown.x + (mouse.x - mouseOnMouseDown.x) * 0.003
  }
  if(grabbedEarth){
    targetEarthRotation.x = targetEarthRotationOnMouseDown.x + (mouse.x - mouseOnMouseDown.x) * 0.005
    targetEarthRotation.y = targetEarthRotationOnMouseDown.y + (mouse.y - mouseOnMouseDown.y) * 0.005
  }
  if(showingDetail){
    targetSceneRotation.y = -(mouse.x - contW / 2) * .00007
    targetSceneRotation.x = -(mouse.y - contH / 2) * .0001
  }
  let obj = updateRaycaster()
  if(obj.name == 'earth-map-border'){
    $cont.css('cursor', '-webkit-grab')
  }else if(obj.name == 'timeline-h'){
    $cont.css('cursor', 'e-resize')
  }else if(obj.name == 'hotspot-h'){
    $cont.css('cursor', 'pointer')
  }else if(obj.name == 'closebtn'){
    $cont.css('cursor', 'pointer')
  }else{
    $cont.css('cursor', 'auto')
  }
}

function onDocumentMouseUp(){
  grabbedEarth = false
  grabbedTimeline = false
}

function render(){
  skybox.rotation.x = earth.rotation.x * .25
  skybox.rotation.y = earth.rotation.y - Math.PI / 180 * 30 * .25
  skybox.rotation.z = earth.rotation.z * .25
  earth.rotation.y += (targetEarthRotation.x - earth.rotation.y) * .05
  earth.rotation.x += (targetEarthRotation.y - earth.rotation.x) * .05
  scene.rotation.y += (targetSceneRotation.y - scene.rotation.y) * .05
  scene.rotation.x += (targetSceneRotation.x - scene.rotation.x) * .05
  timeline.dial.rotation.y += (-targetRotation.x - timeline.dial.rotation.y) * 0.05
  timeline.outerDial.rotation.y = .5 * timeline.dial.rotation.y
  if(targetRotation.x > -1.5) targetRotation.x = -1.5
  if(targetRotation.x < -6.6) targetRotation.x = -6.6
  TWEEN.update()
  requestAnimationFrame(render)
  renderer.render(scene, camera)
}